#include <string>

#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>

#include "config.h"
#include "matrix.h"

const unsigned MESH_VIEW_CTRL = 1 ;
const unsigned MAPPING_VIEW_CTRL = 2 ;
const unsigned BRUSH_SIZE_SLIDER = 3 ;
const unsigned BRUSH_STYLE_BTN = 4 ;

const unsigned COLOR_RED_SLIDER = 5;
const unsigned COLOR_GREEN_SLIDER = 6;
const unsigned COLOR_BLUE_SLIDER = 7;
const unsigned COLOR_ALPHA_SLIDER = 8;

#include "font.h"
#include "shader.h"
#include "texture.h"
#include "gcmesh.h"

#include "brush.h"
#include "model.h"
#include "glview.h"
#include "controls.h"
#include "meshview.h"
#include "mappingview.h"
#include "controller.h"
#include "glcontroller.h"
#include "event.h"

const unsigned window_width = 900 ;
const unsigned window_height = 600 ;

int main(int argc, char* argv[]) 
{
	glutInit(&argc, argv);

	try
	{
		math::ui::Model model ; 
		//model.load_mesh ("../../data/cube1.obj"); 
		//model.load_mesh ("./cube.obj");
		model.load_mesh ("../../data/kitten_manifold_4k.obj"); 
		//model.load_mesh ("../../data/Armadillo_20qem.obj"); 
		//model.load_mesh ("../../data/cossphere.obj");
		//model.load_mesh ("../../data/concave.obj");

		std::cout<<"ALLOCATE MODEL Correctly." <<std::endl;

		math::ui::MeshView glView1(&model, MESH_VIEW_CTRL); 
		glView1.set_viewmode (math::ui::FILL_MODE);
		glView1.set_bgcolor (math::vector<float, 4> (0, 0, 0, 1)); 
		math::ui::MeshViewController glcontroller1(&glView1, & model  ); 



		math::ui::MappingView glView2(&model, MAPPING_VIEW_CTRL);
		glView2.set_viewmode (math::ui::FILL_MODE);
		glView2.set_bgcolor (math::vector<float, 4> (0, 0, 0, 1)); 
		math::ui::GLController glcontroller2(&glView2, & model ); 

		
		// brush controls. switch sytle
		math::ui::StateButton button (& model, BRUSH_STYLE_BTN);
		button.set_viewmode (math::ui::FILL_MODE);
		//button.set_bgcolor (math::vector<float, 4> (0.6, 0.6, 0.6, 1)); 
		button.set_bgcolor (math::vector<float, 4> (0.0, 0.0, 0.0, 1)); 
		button.set_size (200, 50);
		math::ui::StateButtonController buttonController(&button, & model  ); 
		

		math::ui::Slider slider (& model, BRUSH_SIZE_SLIDER);
		slider.set_caption ("Brush Size");
		slider.set_viewmode (math::ui::FILL_MODE);
		//slider.set_bgcolor (math::vector<float, 4> (0.6, 0.6, 0.6, 1)); 
		slider.set_bgcolor (math::vector<float, 4> (0.0, 0.0, 0.0, 1)); 
		slider.set_size (200, 50);
		math::ui::SliderController buttonController2(&slider, & model  ); 
	
		// color controls. 
		// color panel. 

		math::ui::Slider red_slider (& model, COLOR_RED_SLIDER);
		red_slider.set_caption ("Red");
		red_slider.set_viewmode (math::ui::FILL_MODE);
		//slider.set_bgcolor (math::vector<float, 4> (0.6, 0.6, 0.6, 1)); 
		red_slider.set_bgcolor (math::vector<float, 4> (0.0, 0.0, 0.0, 1)); 
		red_slider.set_size (200, 50);
		math::ui::SliderController red_slider_ctrl(&red_slider, & model  ); 


		math::ui::Slider green_slider (& model, COLOR_GREEN_SLIDER);
		green_slider.set_caption ("Green");
		green_slider.set_viewmode (math::ui::FILL_MODE);
		green_slider.set_bgcolor (math::vector<float, 4> (0.0, 0.0, 0.0, 1)); 
		green_slider.set_size (200, 50);
		math::ui::SliderController green_slider_ctrl(&green_slider, & model  ); 


		math::ui::Slider blue_slider (& model, COLOR_BLUE_SLIDER);
		blue_slider.set_caption ("Blue");
		blue_slider.set_viewmode (math::ui::FILL_MODE);
		blue_slider.set_bgcolor (math::vector<float, 4> (0.0, 0.0, 0.0, 1)); 
		blue_slider.set_size (200, 50);
		math::ui::SliderController blue_slider_ctrl(&blue_slider, & model  ); 

		math::ui::Slider alpha_slider (& model, COLOR_ALPHA_SLIDER);
		alpha_slider.set_caption ("Alpha");
		alpha_slider.set_viewmode (math::ui::FILL_MODE);
		alpha_slider.set_bgcolor (math::vector<float, 4> (0.0, 0.0, 0.0, 1)); 
		alpha_slider.set_size (200, 50);
		math::ui::SliderController alpha_slider_ctrl(&alpha_slider, & model  ); 

		
		std::cout<<"ALLOCATE VIEW Correctly."<<std::endl;

		math::ui::EventDispatcher theApp (& model);
		theApp.onRegister (&glcontroller1) ;
		theApp.onRegister (&glcontroller2) ;

		theApp.onRegister (&buttonController2) ; //  brush size
		theApp.onRegister (&buttonController) ;  // brush style

		theApp.onRegister (&red_slider_ctrl) ;
		theApp.onRegister (&green_slider_ctrl) ;
		theApp.onRegister (&blue_slider_ctrl) ;
		theApp.onRegister (&alpha_slider_ctrl) ;

		std::cout<<"ALLOCATE APP."<<std::endl;
		theApp.OnExecute();

		//std::ofstream ostr("./result.obj");
		//ostr << (*model.get_mesh())  ;

	}
	catch (const char * msg)
	{
		std::cerr<<msg<<std::endl;
	}

	return 0; 

}
